package laravel.mvc;

import com.google.common.base.Joiner;
import entity_model.Entity;
import entity_model.Relationship;
import laravel.Laravel;
import laravel.mvc.controller.Controller;
import laravel.mvc.model.Model;
import laravel.mvc.view.View;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import static entity_model.Relationship.Direction.OWNS;
import static php.code.Visibility.PUBLIC;

public class EntityFacade{

    private final Laravel laravel;
    private final Entity entity;
    private final List<MvcComponent> components = new ArrayList<>();

    public EntityFacade(Laravel laravel, Entity entity) {
        this.laravel = laravel;
        this.entity = entity;
    }

    public List<MvcComponent> getComponents() {
        return components;
    }

    public void createComponents() {
        // if (entity.generateModel()) FIXME
            components.add(createModel());

        // if (entity.generateController()) FIXME
        //    components.addColumn(createController());

        // if (entity.generateView()) FIXME
        //    components.addColumn(createView());

        laravel.setOnFinished(this::createRelationships);
    }

    private void createRelationships() {
        entity.getRelateds().forEach(this::create);
    }

    public Model createModel() {
        return new Model(laravel, entity);
    }

    public Controller createController() {
        return new Controller(laravel, entity);
    }

    public View createView() {
        return new View(entity);
    }

    public void create(Relationship.Related related){
        final Relationship.Role theOthersRole = related.getTheOthersRole();
        final Relationship.Role.Cardinality theOthersRoleCardinality = theOthersRole.getCardinality();

        if (theOthersRole.getEntity() == null)
            throw new RuntimeException(related.toString());

        if (theOthersRole.getEntity().toString().equals("null"))
            throw new RuntimeException(related.toString());

        List<Object> args = new ArrayList<>();

        args.add(laravel.models.get(theOthersRole.getEntity().getTitle()));

        // if (related.getDirection().equals(BELONGS_TO))
        //    args.addColumn(related.getTheOthersRoleTitle().suffix("Id").toSnakeCase());

        if (related.getDirection().equals(OWNS))
            args.add(related.getMyRoleTitle().suffix("Id").toSnakeCase());

        Entity pivot = related.getPivot();
        List<String> fillable = null;
        if (pivot != null) {
            args.add(pivot.getTitle().toSnakeCase());
            args.add(related.getMyRoleTitle().getSingularized().suffix("Id").toSnakeCase());
            args.add(related.getTheOthersRoleTitle().getSingularized().suffix("Id").toSnakeCase());
            fillable = laravel.get(pivot).getFillable();
        }

        laravel.models.get(entity.getTitle())
                .getEntityClass()
                .createMethod(
                        PUBLIC,
                        related.getTheOthersRoleTitle()
                )
                .returns(MessageFormat.format("$this->{0}(''{1}''){2}",
                        related.getDirection().getMethodCall(theOthersRoleCardinality),
                        Joiner.on("', '").join(args),
                        fillable == null || fillable.size() == 0? "" : String.format("->withPivot('%s')", Joiner.on("', '").join(fillable))
                ))
                .doc(related.toString());
    }
}
